﻿namespace FBlog.LearningTests.ProofOfConcepts

open Xunit
open System.Linq

module RavenDbPOC =

    type SimpleTestData =
        {
            Id : System.Guid
            SameId : string
            Name : string
            Value : int
        }

    type TestData(id : System.Guid, name : string, value : int) =
        let mutable _id = id
        member x.Id with get() = _id and set(id) = _id <- id
        member x.Name with get() = name
        member x.Value with get() = value

    type TestDataWithList(stringSet : string List) =
        let mutable _id = Unchecked.defaultof<System.Guid>
        member x.Id with get() = _id and set(id) = _id <- id
        member x.StringList with get() = stringSet

    let testGuid = System.Guid.NewGuid()
    let testId = "12345"
    let testName = "MaxMustermann"
    let testValue = 42
    let testStringList = ["abc"; "Hallo Welt"]

    let createSampleData() = { Id = testGuid; SameId = testId; Name = testName; Value = testValue }
    let createData() = new TestData(testGuid, testName, testValue)
    let createDataWithList() = new TestDataWithList(testStringList)

    let createRandomStoreName() =
        let baseName = "ProofOfConceptData"
        let id = System.Guid.NewGuid().ToString()
        sprintf @"c:\temp\%s_%s" baseName id

    let useRavenSession(store : Raven.Client.IDocumentStore, saveChanges : bool) using  =
        use session = store.OpenSession()
        let result = using session
        if saveChanges then session.SaveChanges()
        result

    let removeAllDataFromSession(session : Raven.Client.IDocumentSession) =
        session
            .Query<SimpleTestData>()
            .ToArray()
            |> Seq.iter (fun d -> session.Delete(d.Id) )

    let initializeDocumentStore() =
        let storeName = createRandomStoreName()
        let documentStore = new Raven.Client.Embedded.EmbeddableDocumentStore()
        documentStore.DataDirectory <- storeName
        let store = documentStore.Initialize()
        store

    let saveTo store data =
        useRavenSession (store, true) (fun session -> session.Store(data))

    let documentCountIn store =
        useRavenSession (store, false) (fun session -> session.Query<SimpleTestData>().Count())

    let loadId (id : System.Guid) store : 'a =
        useRavenSession (store, false) (fun session -> session.Load<'a>(id))

    [<Fact>]
    let InitializedStoreShouldBeEmpty() =
        use store = initializeDocumentStore()
        Assert.Equal(0, documentCountIn store)
        
    [<Fact>]
    let CanStoreSimpleTestDataIntoEmbeddedStore() =
        use store = initializeDocumentStore()
        createSampleData() |> saveTo store
        Assert.Equal(1, documentCountIn store)

    [<Fact>]
    let CanReadStoredData() =
        use store = initializeDocumentStore()
        createData() |> saveTo store
        let data : TestData = store |> loadId testGuid

        Assert.Equal(testName, data.Name)
        Assert.Equal(testValue, data.Value)
        Assert.Equal(testGuid, data.Id)

    [<Fact>]
    let CanStoreAndReadDataWithList() =
        use store = initializeDocumentStore()
        let testData = createDataWithList()
        testData |> saveTo store
        let data : TestDataWithList = store |> loadId testData.Id

        Assert.Equal(testData.Id, data.Id)
        Assert.False(testStringList <> testData.StringList)







        
        


